import React, { useState, useRef, useEffect } from 'react'
import { message, Input, Button, Tooltip, Rate, Spin } from 'antd'
import './iFlytek.scss'
import SvgIcon from '@/components/SvgIcon'
import ttsRecorder from './textToVoice/voice.js'
import { useDispatch, useSelector } from 'react-redux'
import { UserActions } from '@/store'
import {
  ProductOutlined,
  SearchOutlined,
  UploadOutlined,
  FrownOutlined,
  MehOutlined,
  SmileOutlined,
} from '@ant-design/icons'
import createXfVoiceInstance from './voiceToText/speak.js'
import dialogue from '@/utils/AiFineTuning.js'
import dialogue2 from '@/utils/Ai.js'
import axios from 'axios'
import { marked } from 'marked'
import TurndownService from 'turndown'
import { baseURL } from '@/setting.ts'
import { reqCreateImg } from '@/api/iFlytek'

const IFlytek = () => {
  const storeUserInfo = useSelector((state: any) => state.user.userInfo)
  // 创建html转markdown的service的实例
  const turndownService = new TurndownService()
  const { TextArea } = Input
  const dispatch: any = useDispatch()
  const limit = useSelector((state: any) => state.user.userInfo.authority)
  const [hide, setHide] = useState(true)
  const ttsWSRef = useRef<WebSocket | null>(null)
  const totalResRef = useRef('')
  const textAreaRef = useRef<any>(null)
  const [question, setQuestion] = useState<string>('')
  const [isEnd, setIsEnd] = useState(true)
  const [sessionProcedure, setSessionProcedure] = useState<any>([])
  const [nav, setNav] = useState(false)
  const [activePage, setActivePage] = useState(1)
  const [proInp, setProInp] = useState('')
  const [showImg, setShowImg] = useState('')
  const [result, setResult] = useState<any>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const ttsWSRef2 = useRef<WebSocket | null>(null)
  const totalResRef2 = useRef<string>('')
  const [output, setOutput] = useState<string>('')
  const [loading, setLoading] = useState(false)
  const [loading2, setLoadin2] = useState(false)
  const [modelLoading, setModelLoading] = useState(false)
  const [isVoice, setIsVoice] = useState(false)
  const [listenEnd, setListenEnd] = useState(true)
  const [ttsInstance, setTtsInstance] = useState<any>(null)
  const xfVoiceRef = useRef<any>(null)

  const customIcons: Record<number, React.ReactNode> = {
    1: <FrownOutlined />,
    2: <FrownOutlined />,
    3: <MehOutlined />,
    4: <SmileOutlined />,
    5: <SmileOutlined />,
  }

  // 大模型回答内容合成为语音输出
  const handleSpeak = (num: number) => {
    let instance = ttsInstance

    if (!instance) {
      instance = new ttsRecorder()
      setTtsInstance(instance)
    }

    instance.setParams({
      text: turndownService.turndown(sessionProcedure[num].answer),
    })

    if (listenEnd) {
      instance.start()
    } else {
      instance.stop()
    }

    setListenEnd(!listenEnd)
  }

  // 语音转文字功能
  const handleTextChange = (newText: any) => {
    setQuestion(newText)
  }

  // 开启语言识别
  const speakStart = () => {
    if (isVoice) {
      xfVoiceRef.current.stop()
      navigator.mediaDevices.getUserMedia({ audio: false })
    } else {
      xfVoiceRef.current.start()
    }
    setIsVoice(!isVoice)
  }

  // 询问大模型
  const askModel = (text = question) => {
    if (!text) {
      message.warning('问题不能为空！')
      return
    }
    if (!isEnd) {
      message.warning('回答还未完毕！')
      return
    }

    hide && setHide(false)

    // 数据创建
    setSessionProcedure((prevSessionProcedure: any) => [
      ...prevSessionProcedure,
      {
        question: text, // 用户提的问题
        answer: totalResRef.current, // 模型的回答（初始为空）
        isEnd: false,
        loading: true,
      },
    ])
    // 对话框数据清除
    setQuestion('')
    // 回答开始
    setIsEnd(false)

    dialogue(
      text,
      ttsWSRef,
      totalResRef,
      () => {
        setSessionProcedure((prevSessionProcedure: any) => {
          // 创建一个副本，并更新最后一个元素的answer字段
          const newSessionProcedure = [...prevSessionProcedure]
          newSessionProcedure[newSessionProcedure.length - 1].answer = marked(totalResRef.current)
          return newSessionProcedure
        })
      },
      (end) => {
        setIsEnd(end)
        setSessionProcedure((prevSessionProcedure: any) => {
          // 创建一个副本，并更新最后一个元素的isEnd字段
          const newSessionProcedure = [...prevSessionProcedure]
          newSessionProcedure[newSessionProcedure.length - 1].isEnd = end
          newSessionProcedure[newSessionProcedure.length - 1].loading = false
          return newSessionProcedure
        })
        totalResRef.current = ''
      },
    )
  }

  // 点击复制回答
  const handleCopyAnswer = (num: number) => {
    navigator.clipboard.writeText(turndownService.turndown(sessionProcedure[num].answer))
    message.success('复制成功！')
  }

  // 打开导航栏
  const handleOpenNav = () => {
    setNav(true)
  }

  // 关闭导航栏
  const handleCloseNav = () => {
    setNav(false)
  }

  // 页面切换
  const handleClickItem = (num: number) => {
    setActivePage(num)
  }

  // 点击生成图片按钮的回调
  const handleCreateImg = async () => {
    if (!proInp) return message.warning('请输入内容！')
    setLoading(true)
    setShowImg('')
    try {
      const res = await reqCreateImg({ text: proInp })
      if (res.code === 200) {
        setShowImg(`data:image/png;base64,${JSON.parse(res.data).payload.choices.text[0].content}`)
      } else {
        message.error('生成失败！')
      }
    } catch (error) {
      let matched = false
      // 遍历关键词进行匹配
      for (const { regex, action } of keywords) {
        if (regex.test(proInp)) {
          await action() // 执行业务逻辑
          matched = true
          break // 停止匹配
        }
      }
      if (!matched) {
        await matchView()
      }
    }

    setProInp('')
    setLoading(false)
  }

  // 定义关键词和对应的业务逻辑函数
  const keywords = [
    { regex: /风景/, action: async () => await matchView() },
    { regex: /猫/, action: async () => await matchCat() },
    { regex: /狗/, action: async () => await matchDog() },
  ]

  // 匹配到狗
  const matchDog = async () => {
    setProInp('')
    const res = await axios.get('https://dog.ceo/api/breeds/image/random')
    setShowImg(res.data.message)
  }

  // 匹配到猫
  const matchCat = async () => {
    setProInp('')
    const res = await axios.get('https://api.thecatapi.com/v1/images/search')
    setShowImg(res.data[0].url)
  }

  // 获取风景图片
  const matchView = async () => {
    setProInp('')
    const res = await axios.get('https://api.oioweb.cn/api/bing')
    const num = Math.floor(Math.random() * 7) + 1
    setShowImg(res.data.result[num].url)
  }

  useEffect(() => {
    getUserInfo()
    xfVoiceRef.current = createXfVoiceInstance(handleTextChange)

    return () => {
      ttsWSRef.current?.close()
      ttsWSRef2.current?.close()
    }
  }, [])

  // 获取个人信息
  const getUserInfo = async () => {
    dispatch(UserActions.getUserInfo())
  }

  // 图片上传
  const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (file) {
      const maxFileSize = 5 * 1024 * 1024
      if (file.size > maxFileSize) {
        message.warning('图片大小不能超过5MB！')
        return
      }

      // 检查文件类型
      const validImageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml']
      if (!validImageTypes.includes(file.type)) {
        message.warning('只能上传图片文件！')
        return
      }

      setLoadin2(true)

      const formData = new FormData()
      formData.append('file', file)
      const res: any = await axios.post('https://api.oioweb.cn/api/ocr/recognition', formData)
      setLoadin2(false)
      if (res.data.code === 200) {
        setResult(res.data.result)
      } else {
        message.error('上传失败！')
      }
    }
  }

  // 点击按钮触发图片上传框
  const handleChangeImg = () => {
    fileInputRef.current!.click()
  }

  // 存储大模型的回答
  const handleMessageReceived = () => {
    setOutput(totalResRef2.current)
  }

  // 是否结束
  const endofJudgment = (_data: boolean) => {
    setModelLoading(false)
  }

  // 结果润色
  const handlePolish = () => {
    const resultTexts = result
      .map((item: any) => `名称: ${item.name}, 根分类:${item.root}, 置信度: ${item.score}`)
      .join('\n')

    const data = `这是图片理解功能的结果
${resultTexts}
你的身份是这个回答这个功能的ai，用语言把这个结果串起来，文本润色一下`
    setModelLoading(true)
    dialogue2(data, ttsWSRef2, totalResRef2, handleMessageReceived, endofJudgment)
  }

  return (
    <div className="IFlytek">
      {limit.module === 1 ? (
        <>
          <div className="IFlytek-toggle">
            {!nav ? (
              <Tooltip placement="right" title="打开导航栏">
                <Button
                  type="primary"
                  icon={<ProductOutlined />}
                  ghost
                  shape="circle"
                  onClick={handleOpenNav}
                  className="toggle-circle"
                ></Button>
              </Tooltip>
            ) : (
              ''
            )}
            <div
              onMouseLeave={handleCloseNav}
              style={{ opacity: nav ? '1' : '0' }}
              className="toggle-content"
            >
              <div
                onClick={() => {
                  handleClickItem(1)
                }}
                className={`tc-Item ${activePage === 1 ? 'tc-Item-active' : ''}`}
              >
                <SvgIcon name="IFlytek-dark" size="20" color="#ffffff"></SvgIcon>
              </div>
              <div
                onClick={() => {
                  handleClickItem(2)
                }}
                className={`tc-Item ${activePage === 2 ? 'tc-Item-active' : ''}`}
              >
                <SvgIcon name="createImg" size="20"></SvgIcon>
              </div>
              <div
                onClick={() => {
                  handleClickItem(3)
                }}
                className={`tc-Item ${activePage === 3 ? 'tc-Item-active' : ''}`}
              >
                <SvgIcon name="analyzeImg" size="20"></SvgIcon>
              </div>
            </div>
          </div>
          {activePage === 1 && (
            <div className="IFlytek-content">
              {!hide ? (
                <div className="IFlytek-main">
                  {sessionProcedure.map((item: any, index: number) => (
                    <div key={index} className="IFlytek-dialog">
                      <div className="dialog-ask">
                        <div className="dialogAsk-top">
                          <img
                            className="dialogAsk-img"
                            src={
                              storeUserInfo.image
                                ? `${baseURL}/img/${storeUserInfo.image}`
                                : '/assets/images/avatar.png'
                            }
                            alt=""
                          />
                          <span>{storeUserInfo.username}</span>
                        </div>
                        <div
                          dangerouslySetInnerHTML={{ __html: item.question }}
                          className="dialogAsk-content"
                        ></div>
                      </div>
                      <div className="dialog-answer">
                        <div className="dialogAnswer-top">
                          <Spin spinning={item.loading}>
                            <img src="/assets/images/IFlytek.png" alt="" />
                          </Spin>

                          <span>讯飞星火</span>
                          <Tooltip placement="right" title={listenEnd ? '播放回答' : '停止播放'}>
                            <div
                              onClick={() => {
                                handleSpeak(index)
                              }}
                            >
                              <SvgIcon name="talk" size="20" />
                            </div>
                          </Tooltip>
                        </div>
                        <div
                          dangerouslySetInnerHTML={{ __html: item.answer }}
                          className="answer-content"
                        ></div>
                        {item.isEnd && (
                          <div style={{ display: 'flex', alignItems: 'center', marginTop: '15px' }}>
                            <Tooltip placement="top" title="复制回答">
                              <div
                                onClick={() => {
                                  handleCopyAnswer(index)
                                }}
                              >
                                <SvgIcon name="copy" size="18"></SvgIcon>
                              </div>
                            </Tooltip>
                            <Rate
                              style={{ margin: '0 0 7px 12px' }}
                              onChange={() => {
                                message.success('感谢您的评价')
                              }}
                              defaultValue={5}
                              character={({ index = 0 }) => customIcons[index + 1]}
                            />
                          </div>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              ) : (
                <div className="introduce">
                  <div className="introduce-top">
                    <img src="/assets/images/IFlytek.png" alt="" />
                  </div>
                  <div className="introduce-content">
                    <div
                      onClick={() => {
                        askModel('告诉我今日武汉天气。')
                      }}
                    >
                      <SvgIcon name="weather" size="30" />
                      <p style={{ marginTop: '20px' }}>告诉我今日天气。</p>
                    </div>
                    <div
                      onClick={() => {
                        askModel('如何理解5G技术对我国经济发展和人民生活的影响？')
                      }}
                    >
                      <SvgIcon name="fiveG" size="30" />
                      <p style={{ marginTop: '20px' }}>
                        如何理解5G技术对我国经济发展和人民生活的影响？
                      </p>
                    </div>
                    <div
                      onClick={() => {
                        askModel('如何有效利用教学硬件提高学习效率？')
                      }}
                    >
                      <SvgIcon name="education" size="30" />
                      <p style={{ marginTop: '20px' }}>如何有效利用教学硬件提高学习效率？</p>
                    </div>
                    <div
                      onClick={() => {
                        askModel('有哪些简单易行的居家锻炼方法，可以帮助提高身体素质？')
                      }}
                    >
                      <SvgIcon name="yoga" size="30" />
                      <p style={{ marginTop: '20px' }}>
                        有哪些简单易行的居家锻炼方法，可以帮助提高身体素质？
                      </p>
                    </div>
                  </div>
                </div>
              )}
              <div className="IFlytek-input">
                <div className="IFlytek-text">
                  <div onClick={speakStart} className="IFlytekInput-icon">
                    <SvgIcon size="40" name="speak" />
                  </div>
                  <TextArea
                    onChange={(e: any) => setQuestion(e.target.value)}
                    onKeyDown={(e) => {
                      if (e.key === 'Enter') {
                        if (!e.shiftKey) {
                          // 如果没有按下Shift键，执行搜索操作
                          askModel()
                          // 阻止默认行为，这样就不会换行
                          e.preventDefault()
                        }
                      }
                    }}
                    ref={textAreaRef}
                    autoSize={{ minRows: 1, maxRows: 10 }}
                    className="IFlytek-textArea"
                    placeholder="请输入你的问题"
                    value={question}
                  ></TextArea>
                  {isEnd ? (
                    <div
                      onClick={() => {
                        askModel()
                      }}
                      className="IFlytekInput-icon"
                    >
                      <SvgIcon size="40" name="search" />
                    </div>
                  ) : (
                    <Tooltip placement="top" title="停止回答">
                      <div
                        onClick={() => {
                          ttsWSRef.current?.close()
                          setIsEnd(true)
                          message.success('回答已停止')
                        }}
                        className="IFlytekInput-icon"
                      >
                        <SvgIcon size="40" name="stop" />
                      </div>
                    </Tooltip>
                  )}
                </div>
                <div className="IFlytek-input-bottom">模型来自讯飞星火，仅做为学习用途</div>
              </div>
            </div>
          )}
          {activePage === 2 && (
            <div className="IFlytek-proImg">
              <div className="proImg-title">图片生成</div>
              <div className="proImg-content">
                <p>规则：输入对要生成的图片的描述，比如：生成一个风景/猫/狗图片</p>
                <div className="proImg-input">
                  <Input
                    size="large"
                    value={proInp}
                    onChange={(e) => setProInp(e.target.value)}
                    style={{ width: '300px', fontSize: '14px', marginRight: '20px' }}
                    placeholder="请输入要生成的图片的描述"
                    onKeyDown={(e) => {
                      if (e.key === 'Enter') {
                        handleCreateImg()
                      }
                    }}
                    prefix={<SearchOutlined />}
                  />
                  <Button size="large" type="primary" onClick={handleCreateImg}>
                    生成
                  </Button>
                </div>
              </div>
              {loading && (
                <div className="wrapper">
                  <div className="circle"></div>
                  <div className="circle"></div>
                  <div className="circle"></div>
                  <div className="shadow"></div>
                  <div className="shadow"></div>
                  <div className="shadow"></div>
                  <span>玩命加载中。。。</span>
                </div>
              )}
              <div className="proImg-img">
                <img src={showImg} alt="" />
              </div>
            </div>
          )}
          {activePage === 3 && (
            <div className="IFlytek-comImg">
              <div className="comImg-title">图片理解</div>
              <div className="comImg-content">
                <input
                  type="file"
                  ref={fileInputRef}
                  style={{ display: 'none' }}
                  onChange={handleFileChange}
                  accept="image/*"
                />
                <Button
                  icon={<UploadOutlined />}
                  type="primary"
                  size="large"
                  ghost
                  onClick={handleChangeImg}
                >
                  上传并识别
                </Button>
                {loading2 && (
                  <div className="wrapper">
                    <div className="circle"></div>
                    <div className="circle"></div>
                    <div className="circle"></div>
                    <div className="shadow"></div>
                    <div className="shadow"></div>
                    <div className="shadow"></div>
                    <span>玩命加载中。。。</span>
                  </div>
                )}
                {result && (
                  <>
                    <div id="result">
                      <h1 style={{ margin: '20px 0' }}>识别结果</h1>
                      {result.map((item: any, index: any) => (
                        <p style={{ marginBottom: '10px' }} key={index}>
                          名称: {item.name}, 根分类: {item.root}, 置信度: {item.score}
                        </p>
                      ))}
                    </div>
                    <Button size="large" onClick={handlePolish} danger style={{ margin: '20px 0' }}>
                      结果润色
                    </Button>
                    {modelLoading && (
                      <div className="wrapper">
                        <div className="circle"></div>
                        <div className="circle"></div>
                        <div className="circle"></div>
                        <div className="shadow"></div>
                        <div className="shadow"></div>
                        <div className="shadow"></div>
                        <span>玩命加载中。。。</span>
                      </div>
                    )}
                    <div
                      dangerouslySetInnerHTML={{ __html: output }}
                      style={{ lineHeight: '1.5' }}
                    ></div>
                  </>
                )}
              </div>
            </div>
          )}
        </>
      ) : (
        <div style={{ marginTop: '35vh', fontSize: '30px', color: 'red', fontWeight: '600' }}>
          没有使用权限
        </div>
      )}
    </div>
  )
}

export default IFlytek
